<?

Class ShowInfo {

  public static function allShows ($xml) {
    
    $toReturn = array();
    
    foreach ($xml->show as $showXML)
      $toReturn[] = new ShowInfo($xml, $showXML->attributes()->seriesID, $showXML->seriesName);

    return $toReturn;
    
  }

  public $seriesName;
  public $seriesID;
  public $nextSeason;
  public $nextEpisode;
  public $nextAirdate;
  public $nextEpName;
  public $airs;
  public $network;
  public $status;
  public $format;
  public $poster;
  public $tvrageurl;

  public $dfa;
  public $dfa_waiting;
 
  public $dlSeason;
  public $dlEpisode;
  public $dlTimestamp;
 
  public $showTVDB;
  public $showXML;
 
  function __construct($xml, $seriesID, $seriesName=false) {

		print_log("Creating object for ID#$seriesID ".(!$seriesName ? '':" ($seriesName)"));

		$this->seriesName = $seriesName;
    $this->seriesID = $seriesID;
    $this->nextSeason = false;
    $this->nextEpisode = false;
    $this->nextAirdate = false;
    $this->nextEpName = false;
    $this->airs = false;
    $this->network = false;
    $this->status = false;
    $this->format = false;
    $this->poster = false;
    $this->tvrageurl = false;
    
    $this->dfa = false;
    $this->dfa_waiting = false;
    $this->daily = false;
    
    $this->dlSeason = false;
    $this->dlEpisode = false;
    $this->dlTimestamp = false;
    $this->dlAirdate = false;

    $this->showTVDB = false;
    $this->showTVRage = false;
    $this->showXML = false;

    for ($i = 0; $i < count($xml->show); $i++) {
      if($xml->show[$i]->attributes()->seriesID == $seriesID) {
        $this->showXML = $xml->show[$i];
        break;
      }
    }
    
    // if we didn't find it in the XML then we have to make our own
    if ($this->showXML === false) {
      $showXML = $xml->addChild('show');
      $showXML->addAttribute('seriesID', $seriesID);
      if ($seriesName !== false)
        $showXML->addChild('seriesName', $seriesName);
      $this->showXML = $showXML;
    }

    $this->update();
    
  }

  function getTVDB () {
    global $tvdb_up;
  
    if ($this->showTVDB !== false)
      return $this->showTVDB;
    
    if ($tvdb_up === false)
      return null;
    
    if ($this->seriesID !== false) {
      $return = TV_Shows::findById($this->seriesID);
      if ($return === false)
        return null;
      else
        return $return;
    }
    
    if ($this->seriesName !== false) {
  		print "searching for $this->seriesName\n";
      $shows = TV_Shows::search($this->seriesName);
      if (count($shows) > 0)
        return $shows[0];
      else
        return null;
    }
    
    return false;
    
  }
  
  function getTVRage () {
    global $tvrage_up;
  
    if ($this->showTVRage !== false)
      return $this->showTVRage;
    
    if ($tvrage_up === false)
      return null;
    
    if ($this->seriesName !== false)
      return TVRage_Show::getShow($this->seriesName);
      
    return false;
  
  }
  
  function isTVDBGood() {
    global $tvdb_up;
    if ($this->showTVDB == null || $this->showTVDB === false || $tvdb_up === false)
      return false;
    else
      return true;
  }
  
  function isTVRageGood() {
    global $tvrage_up;
    if ($this->showTVRage == null || $this->showTVRage === false || $tvrage_up === false)
      return false;
    else
      return true;
  }
  
  
  function printIt () {
   
    print "====================\n";
    print "Show Name: $this->seriesName\n";
    print "Series ID: $this->seriesID\n";
    print "Next episode: $this->nextSeason x $this->nextEpisode on $this->nextAirdate - $this->nextEpName\n";
    print "Airs: $this->airs\n";
    print "Network: $this->network\n";
    print "Status: $this->status\n";
    print "Year: $this->year\n";
    print "Format: $this->format\n";
    print "Poster: $this->poster\n";
    print "Last download: $this->dlSeason x $this->dlEpisode ($this->dlAirdate) on $this->dlTimestamp\n";
    print "====================\n";

  }

  function update() {

    $showXML = $this->showXML;
    
    // save the changes to XML
    $this->saveToXML();

    // get our TVDB object
    $this->showTVDB = $this->getTVDB();

    // do this first so we can get the TVRage info from it
    $this->seriesName = ($this->isTVDBGood() ? $this->showTVDB->seriesName : $showXML->seriesName);
    $this->seriesID = ($this->isTVDBGood() ? $this->showTVDB->id : $showXML->attributes()->seriesID);

    // get our TVRage object
    $this->showTVRage = $this->getTVRage();
    
    $lastDLIndex = count($showXML->downloads->download)-1;
    // if we've changed it since we loaded the XML then we want to just use those values
    if ((int)$showXML->dlSeason != $this->dlSeason || (int)$showXML->dlEpisode != $this->dlEpisode) {

      // if it's in the XML then use that
      if (!empty($showXML->dlSeason) && !empty($showXML->dlEpisode)) {
        $this->dlSeason = (int)$showXML->dlSeason;
        $this->dlEpisode = (int)$showXML->dlEpisode;
        $this->dlTimestamp = (int)$showXML->dlTimestamp;
        $this->dlAirdate = (int)$showXML->dlAirdate;
    
      // try getting it from the download history
      } else if (!empty($showXML->downloads) && $lastDLIndex >= 0) {
        $this->dlSeason = (int)$showXML->downloads->download[$lastDLIndex]->season;
        $this->dlEpisode = (int)$showXML->downloads->download[$lastDLIndex]->episode;
        $this->dlTimestamp = (int)$showXML->downloads->download[$lastDLIndex]->timestamp;
        $this->dlAirdate = (int)$showXML->downloads->download[$lastDLIndex]->airdate;
      
      // if we couldn't get it from the download history and the XML doesn't have it either then zero it out
      } else if (empty($showXML->dlSeason) || empty($showXML->dlEpisode)){
        $this->dlSeason = 1;
        $this->dlEpisode = 0;
        $this->dlTimestamp = 0;
        $this->dlAirdate = 0;
      }
    }
      
    // if next episode is blank then fill it, otherwise just leave it (we'll update it when we download something)
    $actualNextEp = false;
    if (empty($this->nextEpisode) || empty($this->nextSeason) || empty($this->nextAirdate)) {
    
      // try TVRage first
      $nextEp = $this->TVRAGE_comingEpisode($this->dlSeason, $this->dlEpisode);

      // if we didn't get complete next ep info from TVRage try TVDB
      if ($nextEp === false || empty($nextEp['season']) || empty($nextEp['episode']) || empty($nextEp['airdate'])) {
        $nextEp2 = $this->TVDB_comingEpisode($this->dlSeason, $this->dlEpisode);
      }

      // if we got complete info from tvrage then use it, if it's sketchy then just use tvdb (probably both blank but you never know)
      if ($nextEp2 !== false && !empty($nextEp2['season']) && !empty($nextEp2['episode']) && !empty($nextEp2['airdate']))
        $actualNextEp = $nextEp2;
      else
        $actualNextEp = $nextEp;

    }

    // if I can't get the actual "coming" episode info, it could be because there are no episodes past this date but I still haven't got the last episode (2 eps airing on the same day for example)
    // if that's the case, try just getting the "next" episode rather than the "coming" episode
    if ($actualNextEp !== false && empty($actualNextEp['season']) && empty($actualNextEp['episode'])) {
      $nextEp3 = $this->TVDB_nextEpisode($this->dlSeason, $this->dlEpisode);
      if ($nextEp3['airdate'] > 0)
        $actualNextEp = $nextEp3;
    }
    
    // if nobody will tell us when the next ep is then just use our old info
    if ($actualNextEp !== false) {
      $this->nextSeason = (int)$actualNextEp['season'];
      $this->nextEpisode = (int)$actualNextEp['episode'];
      $this->nextAirdate = $actualNextEp['airdate'];
      $this->nextEpName = $actualNextEp['name'];
    } else {
      $this->nextSeason = (int)$showXML->nextSeason;
      $this->nextEpisode = (int)$showXML->nextEpisode;
      $this->nextAirdate = (int)$showXML->nextAirdate;
      $this->nextEpName = $showXML->nextEpName;
    }

    // some stuff should come from TVRage if possible (info is more complete)
    if ($this->isTVRageGood()) {
      $this->network = $this->showTVRage->network;
      $this->airs = strtotime(str_replace("at ", "", $this->showTVRage->airs));
    } else if ($this->isTVDBGood() && !empty($this->showTVDB->daysOfWeek) && !empty($this->showTVDB->airTime)) {
      $this->airs = strtotime($this->showTVDB->daysOfWeek.' '.$this->showTVDB->airTime);
      $this->network = $this->showTVDB->network;
    } else {
      $this->network = $showXML->network;
      $this->airs = $showXML->airs;
    }

    if ($this->isTVRageGood())
      $this->status = $this->getTVRage()->status;
    else if ($this->isTVDBGood())
      $this->status = $this->getTVDB()->status;
    else
      $this->status = $showXML->status;

    $this->format = $showXML->format;
    $this->poster = $showXML->poster;
    $this->tvrageurl = $showXML->tvrageurl;
    $this->dfa = $showXML->dfa;
    $this->dfa_waiting = $showXML->dfa_waiting;
    $this->daily = $showXML->daily;
   
    $this->saveToXML();
   
  }
 
  // note: can be undone by doing a saveToXML()
  function delete () {
    unset($this->showXML);
  }
 
  function saveToXML () {
 
    if (!$this->showXML->attributes()->seriesID) $this->showXML->addAttribute('seriesID', $this->seriesID);
    else if ($this->seriesID !== false) $this->showXML->attributes()->seriesID = trim($this->seriesID);
 
    if (!$this->showXML->seriesName) $this->showXML->addChild('seriesName', htmlspecialchars($this->seriesName));
    else if ($this->seriesName !== false) $this->showXML->seriesName = htmlspecialchars(trim($this->seriesName));
 
    if (!$this->showXML->nextSeason) $this->showXML->addChild('nextSeason', $this->nextSeason);
    else if ($this->nextSeason !== false) $this->showXML->nextSeason = trim($this->nextSeason);
 
    if (!$this->showXML->nextEpisode) $this->showXML->addChild('nextEpisode', $this->nextEpisode);
    else if ($this->nextEpisode !== false) $this->showXML->nextEpisode = trim($this->nextEpisode);
 
    if (!$this->showXML->nextEpName) $this->showXML->addChild('nextEpName', htmlspecialchars($this->nextEpName));
    else if ($this->nextEpName !== false) $this->showXML->nextEpName = htmlspecialchars(trim($this->nextEpName));
 
    if (!$this->showXML->nextAirdate) $this->showXML->addChild('nextAirdate', $this->nextAirdate);
    else if ($this->nextAirdate !== false) $this->showXML->nextAirdate = trim($this->nextAirdate);
 
    if (!$this->showXML->dlSeason) $this->showXML->addChild('dlSeason', $this->dlSeason);
    else if ($this->dlSeason !== false) $this->showXML->dlSeason = trim($this->dlSeason);

    if (!$this->showXML->dlEpisode) $this->showXML->addChild('dlEpisode', $this->dlEpisode);
    else if ($this->dlEpisode !== false) $this->showXML->dlEpisode = trim($this->dlEpisode);

    if (!$this->showXML->dlTimestamp) $this->showXML->addChild('dlTimestamp', $this->dlTimestamp);
    else if ($this->dlTimestamp !== false) $this->showXML->dlTimestamp = trim($this->dlTimestamp);

    if (!$this->showXML->dlAirdate) $this->showXML->addChild('dlAirdate', $this->dlAirdate);
    else if ($this->dlAirdate !== false) $this->showXML->dlAirdate = trim($this->dlAirdate);

    if (!$this->showXML->airs) $this->showXML->addChild('airs', $this->airs);
    else if ($this->airs !== false) $this->showXML->airs = trim($this->airs);
 
    if (!$this->showXML->network) $this->showXML->addChild('network', $this->network);
    else if ($this->network !== false) $this->showXML->network = trim($this->network);
 
    if (!$this->showXML->status) $this->showXML->addChild('status', $this->status);
    else if ($this->status !== false) $this->showXML->status = trim($this->status);
 
    if (!$this->showXML->format) $this->showXML->addChild('format', $this->format);
    else if ($this->format !== false) $this->showXML->format = trim($this->format);
 
    if (!$this->showXML->poster) $this->showXML->addChild('poster', $this->poster);
    else if ($this->poster !== false) $this->showXML->poster = trim($this->poster);
    
    if (!$this->showXML->tvrageurl) $this->showXML->addChild('tvrageurl', $this->tvrageurl);
    else if ($this->tvrageurl !== false) $this->showXML->tvrageurl = trim($this->tvrageurl);
    
    if (!$this->showXML->dfa) $this->showXML->addChild('dfa', $this->dfa);
    else if ($this->dfa !== false) $this->showXML->dfa = trim($this->dfa);
    
    if (!$this->showXML->dfa_waiting) $this->showXML->addChild('dfa_waiting', $this->dfa_waiting);
    else if ($this->dfa_waiting !== false) $this->showXML->dfa_waiting = trim($this->dfa_waiting);
    
    if (!$this->showXML->daily) $this->showXML->addChild('daily', $this->daily);
    else if ($this->daily !== false) $this->showXML->daily = trim($this->daily);
    
  }
 
  function oneEpisodeBehind ($season=false, $episode=false) {
  
    if ($season === false)
      $season = (int)$this->dlSeason;
    if ($episode === false)
      $episode = (int)$this->dlEpisode;

    // if we're too far along return null (we're confused)
    if ($season == (int)$this->nextSeason && $episode > (int)$this->nextEpisode)
      return null;
    if ($season > (int)($this->nextSeason+1))
      return null;
      
    // if we're one ep behind return true
    if ($season == (int)$this->nextSeason && $episode == (int)($this->nextEpisode - 1))
      return true;
      
    // all of these cases mean we're more than 1 episode behind
    if ($season < (int)($this->nextSeason-1))
      return false;
    else if ($season == (int)$this->nextSeason && $episode < (int)($this->nextEpisode-1))
      return false;

    // try checking our tvrage object to see if it knows
    if ($this->isTVRageGood() && $this->getTVRage()->lastSeason == $season && $this->getTVRage()->lastEpisode == $episode && $this->getTVRage()->nextSeason !== false && $this->getTVRage()->nextEpisode !== false)
      return true;
 
    // cover season-flipping case (this actually covers all cases but is way more expensive than the above
    if ($season == $this->nextSeason - 1) {
    
      $myNextEpisode = $this->TVDB_nextEpisode($season, $episode);

      // if we've got this far and TVDB doesn't even know what comes next then we can't say either way (null = maybe)
      if ($myNextEpisode === false)
        return null;

      // if the next episode on TVDB is actually the what we have in our next episode then we're only one episode behind
      if ($this->nextSeason == $myNextEpisode['season'] && $this->nextEpisode == $myNextEpisode['episode'])
        return true;
      else
        return false;
       
    } else
      return null;
  }
  
  function TVDB_nextEpisode ($curSeason = 1, $curEpisode = 0) {

    if (!$this->isTVDBGood()) {
      print_log("Unable to create TVDB object (thetvdb.com is down or bad showname/series id)");
      $tvdb_up = false;
      return false;
    }

    $myShow = $this->getTVDB();
       
    $season = $curSeason;
    $episode = $curEpisode;
   
    // try the next episode
    $episode += 1;
   
    $myEpisode = $myShow->getEpisode($season, $episode);
   
    // if we can't find it maybe it's in the next season
    if ($myEpisode === false) {
      $season += 1;
      $episode = 1;
      $myEpisode = $myShow->getEpisode($season, $episode);
    }
    // if we still can't find it then I guess this is the last one
    if ($myEpisode === false)
      return false;

    return array('season' => $season, 'episode' => $episode, 'airdate' => $myEpisode->firstAired, 'name' => $name);
   
}
   
// $curseason and $curepisode are the last episode we already have downloaded
function TVDB_comingEpisode ($curSeason = 1, $curEpisode = 0) {
   
    global $tvdb_up;
   
    $return = array('season' => '', 'episode' => '', 'airdate' => '', 'name' => '');
   
    if (!$this->isTVDBGood()) {
      print_log("Unable to create TVDB object (thetvdb.com is down or bad showname/series id)");
      $tvdb_up = false;
      return false;
    }

    $myShow = $this->getTVDB();   
    
    $season = $curSeason;
    $episode = $curEpisode;
    $airdate = 0;
   
    while ($airdate < strtotime(date("d M Y"))) {
   
      // try the next episode
      $episode += 1;

      $myEpisode = $myShow->getEpisode($season, $episode);
   
      // if we don't know when it's airing then we're out of reliable info, return blank
      if (empty($myEpisode->firstAired))
        return $return;
   
      // if we can't find it maybe it's in the next season
      if ($myEpisode === false) {
        $myEpisode = $myShow->getEpisode($season+1, 1);
        if ($myEpisode !== false) {
          $season += 1;
          $episode = 1;
        } else
          return $return;
      }
   
      $airdate = $myEpisode->firstAired;
      $name = $myEpisode->name;
      
    }
   
    return array('season' => $season, 'episode' => $episode, 'airdate' => $airdate, 'name' => $name);
   
}
   
// get the episode that airs next from tvrage.com
function TVRAGE_comingEpisode ($curSeason=1, $curEpisode=0) {

    global $tvrage_up;

    if ($this->isTVRageGood() !== true) {
      print_log("Unable to create TVRage object (tvrage.com is down)");
      $tvrage_up = false;
      return false;
    }

    $myShow = $this->getTVRage();

    return $myShow->comingEpisode($curSeason, $curEpisode);
}


}
?>
